﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ScFramework.Core;
using System;
public sealed class EntityDataManager : LogicModuleBase<UserManager,LocalServer>, IEntityDataManager, ICompDataManager,ISharedEntityDataManager
{
    UInt16 entityUsedCnt = 1;

    HashSet<Tuple<ushort, ushort>> ignoreSet = null;
    //  EntityDataManager _instance;
    public override void OnInit(object args = null)
    {
        base.OnInit(args);
        ComponentDataExtensions.SetManager(this);
        SysModule1.RegisterDataManager(this);
        ignoreSet = new HashSet<Tuple<ushort, ushort>>();
    }
    public override void OnDestroy()
    {
        base.OnDestroy();
        ComponentDataExtensions.DelManager();
        ignoreSet = null;
    }
    /// <summary>
    /// 实体数据集合
    /// </summary>
    Dictionary<UInt16, EntityData> entityDatas = new Dictionary<ushort, EntityData>();

   // public ushort EntityDataCnt => (ushort)entityDatas.Count;

    /// <summary>
    /// 根据id获取实体数据
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public EntityData GetEntityData(UInt16 id)
    {

        if (entityDatas.ContainsKey(id))
        {
            return entityDatas[id];
        }
        else
        {
        //    Debug.Log($"entity {id} is null");
            return null;
        }
    }


    [RegisterEvent( PhysicsProcessEvent.EntityData_SelectInstance)]
    void SelectInstance(object args = null)
    {
        var list = new List<EntityData>();
        var tplis = new List<EntityData>();
        HashSet<int> hashset = new HashSet<int>();
        foreach (var x in entityDatas.Values)
        {
            if (x.GetComponentData<STransform>()!=null)
            {
                if (x.GetComponentData<SComBody>() != null)
                {

                    if (x.GetComponentData<SComBody>().GetValue<int>("PresentPos") == 0)
                    {
                        tplis.Add(x);
                    }
                }
                else if (x.GetComponentData<SRigidUnion>() != null)
                {
                    tplis.Add(x);
                    if (GameMode.Instance.PosChecker(x.GetComponentData<SRigidUnion>().GetValue<Vector3>(STransformVEx.LocalPositionId)))
                    {
                        hashset.Add(GetInnerModule<IBelongUser>().GetBelongUser(x.EntityIdentity.right()));
                    }
                }
                else if(GameMode.Instance.PosChecker(x.GetComponentData<STransform>().GetValue<Vector3>(STransformVEx.LocalPositionId)))
                {
                    list.Add(x);
                }
            }
        }
      
        foreach(var x in tplis)
        {
            if (hashset.Contains(GetInnerModule<IBelongUser>().GetBelongUser(x.EntityIdentity.right())))
            {
                list.Add(x);
            }
        }
        Dispatch<PhysicsProcessEvent>(PhysicsProcessEvent.SyncInstance, GameMode.Instance.SelectInstance(list));
    }


    /// <summary>
    /// 根据二进制数据流初始化数据
    /// </summary>
    /// <param name="data"></param>
   // [RegisterEvent(typeof(PhysicsProcessEvent), PhysicsProcessEvent.EntityData_Init)]
   
    public void InitData(byte[] data = null)
    {
        entityUsedCnt = 1;
        entityDatas = new Dictionary<ushort, EntityData>();


    }

    private Action<EntityData> __tempAct = null;
    #region Create
    /// <summary>
    /// 主机请求创建
    /// </summary>
    /// <param name="args"></param>
    [RegisterEvent(EntityDataEvent.Create)]
    void CreateEntityData(DataCreateArgs args)
    {
        Debug.Assert(SysModule.IsHost);
        __tempAct = args.actions;
        //     Debug.Assert(SysModule.IsHost);
         CreateEntityData(args.ID);

        Debug.Assert(__tempAct == null);
    /*    if (args.actions != null)
        {
            args.actions(entityDatas[id]);
        }*/
        return;
    }
    /// <summary>
    /// 主机请求创建
    /// </summary>
    /// <param name="prefabID"></param>
    /// <returns></returns>
    [RegisterEvent(EntityDataEvent.Create)]
    UInt16 CreateEntityData(UInt16 prefabID)
    {
        while (GetEntityData(entityUsedCnt) != null) entityUsedCnt++;
        ushort id = entityUsedCnt++;
        CreateEntityDataLocal(prefabID.combine(id));
        return id;
    }
    /// <summary>
    /// 本地执行创建
    /// </summary>
    /// <param name="entityID"></param>
    /// <returns></returns>
    [RegisterEvent(EntityDataEvent.Create)]
    UInt16 CreateEntityDataLocal(UInt32 entityID)
    {
        Debug.Assert(GetEntityData(entityID.right()) == null);

        var data = CreateEmptyData(entityID);
        entityDatas[data.EntityIdentity.right()] = data;

        if (__tempAct != null)
        {
            __tempAct(data);
            __tempAct = null;
        }

        Dispatch(EntityDataEvent.Created, data);
        if (SysModule.IsHost)
        {
            Dispatch(EntityDataReq.Create, data.EntityIdentity);
        }
        return data.EntityIdentity.right();
    }
    EntityData CreateEmptyData(UInt32 prefabID)
    {
        var data = new EntityData();
        var prefab = EntityUtilities.GetPrefab(prefabID.left());
        ushort cnt = 0;
        foreach(var x in prefab.GetAll<SComponent>())
        {
            data.ComponentDatas.Add(new ComponentData { ComponentType= x.GetType(),Values=new List<ValueBase>() ,CompIdentity=prefabID.right().combine(cnt++),EntityPrefabID=prefabID.left()});
        }
        data.EntityIdentity = prefabID;
        return data;
    }
    #endregion
    #region Delete

    [RegisterEvent(EntityDataEvent.Delete)]
    bool DeleteEntityLocal(UInt16 id)
    {
   //     Debug.Assert(entityDatas.ContainsKey(id) && entityDatas[id].EntityIdentity.right() == id);
        bool flag = entityDatas.ContainsKey(id);
            Dispatch(EntityDataEvent.Deleting, id);
        entityDatas.Remove(id);
        ignoreSet.RemoveWhere(s => s.Item1 == id || s.Item2 == id);
        if (flag)
        {
            Dispatch(EntityDataEvent.Deleted, id);
            if (SysModule.IsHost)
            {
                Dispatch(EntityDataReq.Delete, id);
            }
        }
        return flag;
    }
    #endregion
    #region ChangeValue
    [RegisterEvent(EntityDataEvent.ValueChange)]
    public bool ChangeValueLocal(ValueChangeArgs args)
    {
        UInt16 id = args.EntityID;
        UInt32 valueID = args.ValueID;
        object value = args.Value;
        if (GetEntityData(id) == null)
        {
            Debug.LogWarning($"{id }:此实体不存在");
        }

        return GetEntityData(id).GetComponentData((ushort)(valueID >> 16)).SetValue((UInt16)(valueID&((1<<16)-1)), value);
    }

    public void DispathValueChangeMsg(ValueChangeArgs args,bool isReq)
    {
        Dispatch(EntityDataEvent.ValueChanged,args);
        if (isReq||SysModule.IsHost)
        {
            Dispatch(EntityDataReq.ValueChange, args);
        }
    }

    public List<EntityData> GetAllData()
    {
        var list = new List<EntityData>();
        foreach(var x in entityDatas.Values)
        {
            list.Add(x);
        }
        return list;
    }

    public Dictionary<ushort, EntityData>.ValueCollection GetEntitiesCollection()
    {
        return entityDatas.Values;
    }

    public void AddIgnorePair(ushort e1, ushort e2)
    {
        ignoreSet.Add(new Tuple<ushort, ushort>(e1, e2));
        ignoreSet.Add(new Tuple<ushort, ushort>(e2, e1));
    }

    public bool IsIgnored(ushort e1, ushort e2)
    {
        if (e1 == e2) return true;
        else return ignoreSet.Contains(new Tuple<ushort, ushort>(e1, e2));
    }

    public void DelIgnorePair(ushort e1, ushort e2)
    {
        ignoreSet.Remove(new Tuple<ushort, ushort>(e1, e2));
        ignoreSet.Remove(new Tuple<ushort, ushort>(e2, e1));
    }
    #endregion
}
public interface IEntityDataManager
{
    void InitData(byte[]data);
    Dictionary<ushort,EntityData>.ValueCollection GetEntitiesCollection();
    EntityData GetEntityData(UInt16 id);
  //  void ChangeValue<T>(UInt16 id, UInt32 valueID,T value);
}
public interface ISharedEntityDataManager
{
    List<EntityData> GetAllData();
}
public interface ICompDataManager
{
  //  void RequestValueChange(UInt16 entityId, UInt32 valueID, object value);
    void DispathValueChangeMsg(ValueChangeArgs args,bool isReq);
    EntityData GetEntityData(UInt16 id);

    void AddIgnorePair(ushort e1, ushort e2);
    bool IsIgnored(ushort e1, ushort e2);
    void DelIgnorePair(ushort e1, ushort e2);
}
public class DataCreateArgs
{
    public UInt16 ID;
    public Action<EntityData> actions = null;
}

public enum EntityDataReq
{
    Create,
    Delete,
 //   Created,
 //   Deleted,
    ValueChange,
 //   ValueChanged

}
public enum EntityDataEvent
{
    Delete,
    Deleting,
    Deleted,
    Create,
    Created,
    ValueChange,
    ValueChanged

}



public interface IVEx
{
    UInt32 CompIdentity { get; }
    ComponentData Data { get; }
    Type TargetType { get; }
    void SetData(ComponentData d);
}